package org.footballmanager.pandafootball.system.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.footballmanager.pandafootball.common.annotation.SystemServiceLog;
import org.footballmanager.pandafootball.common.constants.Constants;
import org.footballmanager.pandafootball.system.domain.FootClub;
import org.footballmanager.pandafootball.system.domain.FootCupbm;
import org.footballmanager.pandafootball.system.mapper.FootCupbmMapper;
import org.footballmanager.pandafootball.system.service.FootClubService;
import org.footballmanager.pandafootball.system.service.FootCupbfService;
import org.footballmanager.pandafootball.system.service.FootCupbmService;
import org.footballmanager.pandafootball.system.service.FootSjService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.ui.Model;

import javax.servlet.http.HttpServletRequest;
import java.util.*;

@Slf4j
@Service
public class FootCupbmServiceImpl extends ServiceImpl<FootCupbm> implements FootCupbmService {
    private static final String DZNUM = "dznum";
    @Autowired
    private FootCupbmMapper footCupbmMapper;
    @Autowired
    private FootSjService footSjService;
    @Autowired
    private FootClubService footClubService;
    @Autowired
    private FootCupbfService footCupbfService;

    /**
     * 添加各种杯赛的报分记录
     *
     * @param times   第几次报分
     * @param request 请求
     */
    @Override
    @SystemServiceLog(description = "添加各种杯赛的报分记录")
    public void endCupGames(int times, HttpServletRequest request) {
        //添加16强报分记录
        footCupbfService.createBf(times, true, request);
        //添加32强报分记录
        footCupbfService.createBf(times, false, request);
    }

    /**
     * 根据用户主键查找杯赛报名信息
     *
     * @param userId 用户主键
     * @return 杯赛报名信息
     */
    @Override
    @SystemServiceLog(description = "根据用户主键查找杯赛报名信息")
    public FootCupbm findCupbmByUserid(Long userId) {
        Map<String, Object> map = new HashMap<>();
        map.put("sj", footSjService.getSj());
        map.put(Constants.USERID, userId);
        List<FootCupbm> list = footCupbmMapper.findByMap(map);
        if (list != null && !list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据赛季、杯赛类型、杯赛进程获取杯赛报名信息
     *
     * @param sjId  赛季主键
     * @param type  杯赛类型
     * @param staff 杯赛进程
     * @return 杯赛报名信息列表
     */
    @Override
    @SystemServiceLog(description = "根据赛季、杯赛类型、杯赛进程获取杯赛报名信息")
    public List<FootCupbm> findList(Long sjId, boolean type, int staff) {
        Map<String, Object> map = new HashMap<>();
        map.put("sj", sjId);
        map.put("type", type);
        map.put(DZNUM, 0); //不等于
        List<FootCupbm> list = footCupbmMapper.findByMap(map);
        List<FootCupbm> newList = new ArrayList<>();
        if (list == null || list.isEmpty()) {
            return list;
        }
        processSwitch(staff, list, newList);
        return newList;
    }

    /**
     * 处理类型
     *
     * @param staff   人数
     * @param list    报名列表
     * @param newList 新的报名列表
     */
    private void processSwitch(int staff, List<FootCupbm> list, List<FootCupbm> newList) {
        if (staff == 16) {
            newList.addAll(list);
        } else if (staff == 8) {
            processStaff8(list, newList);
        } else if (staff == 4) {
            processStaff4(list, newList);
        } else if (staff == 2) {
            processStaff2(list, newList);
        } else if (staff == 1) {
            processStaff1(list, newList);
        }
    }

    /**
     * 处理16强数据
     *
     * @param list    报名列表
     * @param newList 新的报名列表
     */
    private void processStaff8(List<FootCupbm> list, List<FootCupbm> newList) {
        for (int i = 0; i < list.size(); i = i + 2) {
            boolean isAdd = false;
            for (int j = 0; j < 2; j++) {
                FootCupbm fc = list.get(i + j);
                if (fc.getJj1()) {
                    newList.add(fc);
                    isAdd = true;
                }
            }
            if (!isAdd) {
                newList.add(new FootCupbm());
            }
        }
    }

    /**
     * 处理8强数据
     *
     * @param list    报名列表
     * @param newList 新的报名列表
     */
    private void processStaff4(List<FootCupbm> list, List<FootCupbm> newList) {
        for (int i = 0; i < list.size(); i = i + 4) {
            boolean isAdd = false;
            for (int j = 0; j < 4; j++) {
                FootCupbm fc = list.get(i + j);
                if (fc.getJj2()) {
                    newList.add(fc);
                    isAdd = true;
                }
            }
            if (!isAdd) {
                newList.add(new FootCupbm());
            }
        }
    }

    /**
     * 处理4强数据
     *
     * @param list    报名列表
     * @param newList 新的报名列表
     */
    private void processStaff2(List<FootCupbm> list, List<FootCupbm> newList) {
        for (int i = 0; i < list.size(); i = i + 8) {
            boolean isAdd = false;
            for (int j = 0; j < 8; j++) {
                FootCupbm fc = list.get(i + j);
                if (fc.getJj3()) {
                    newList.add(fc);
                    isAdd = true;
                }
            }
            if (!isAdd) {
                newList.add(new FootCupbm());
            }
        }
    }

    /**
     * 处理冠亚军数据
     *
     * @param list    报名列表
     * @param newList 新的报名列表
     */
    private void processStaff1(List<FootCupbm> list, List<FootCupbm> newList) {
        for (FootCupbm fc : list) {
            if (fc.getJj4()) {
                newList.add(fc);
            }
        }
        if (newList.isEmpty()) {
            newList.add(new FootCupbm());
        }
    }

    /**
     * 根据赛季信息报名冠军杯和联盟杯
     *
     * @param request 请求
     */
    @Override
    @SystemServiceLog(description = "根据赛季信息报名冠军杯和联盟杯")
    public void addTeam2Table(HttpServletRequest request) {
        //获取常规赛的名次，并报名杯赛
        LinkedList<FootCupbm> link16 = new LinkedList<>();
        LinkedList<FootCupbm> link32 = new LinkedList<>();
        List<FootClub> list = footClubService.getScoreboard(false, footSjService.getSj());
        if (null != list && !list.isEmpty()) {
            for (int i = 0; i < 16; i++) {
                if (i >= list.size()) {
                    link16.add(i, saveBmInfo(i, null, true, request));
                } else {
                    link16.add(i, saveBmInfo(i, list.get(i).getUserId(), true, request));
                }
            }
            randomSortBmList(link16, request);
            for (int i = 16; i < 32; i++) {
                if (i >= list.size()) {
                    link32.add(i - 16, saveBmInfo(i - 16, null, false, request));
                } else {
                    link32.add(i - 16, saveBmInfo(i - 16, list.get(i).getUserId(), false, request));
                }
            }
            randomSortBmList(link32, request);
        }
    }

    /**
     * 随机打乱对阵顺序
     *
     * @param temp    报名链表
     * @param request 请求
     */
    private void randomSortBmList(LinkedList<FootCupbm> temp, HttpServletRequest request) {
        //取数
        Random rand = new Random();
        for (int i = 0; i < 16; i++) {
            int num;
            if ((temp.size() - 1) == 0) {
                num = 0;
            } else {
                num = rand.nextInt(temp.size() - 1);
            }
            FootCupbm fc = temp.get(num);
            fc.setDznum(i + 1);
            this.updateNotNull(fc, request);
            temp.remove(num);
        }
    }

    /**
     * 保存新的杯赛到数据库
     *
     * @param num     数量
     * @param userId  用户主键
     * @param type    true 冠军杯 false 联盟杯
     * @param request 请求
     * @return 报名信息
     */
    private FootCupbm saveBmInfo(int num, Long userId, boolean type, HttpServletRequest request) {
        FootCupbm bm = new FootCupbm();
        bm.setDznum(num);
        bm.setJoinDate(new Date());
        bm.setSj(footSjService.getSj());
        bm.setUserId(userId);
        bm.setType(type);
        this.save(bm, request);
        return bm;
    }

    /**
     * 根据杯赛类型获取当前赛季的第一名
     *
     * @param type 类型
     * @return 当前赛季的第一名
     */
    @Override
    @SystemServiceLog(description = "根据杯赛类型获取当前赛季的第一名")
    public FootCupbm getTop1(boolean type) {
        Map<String, Object> map = new HashMap<>();
        map.put("sj", footSjService.getSj());
        map.put("type", type);
        map.put(DZNUM, 0); //不等于
        map.put("jj4", true);
        List<FootCupbm> list = footCupbmMapper.findByMap(map);
        if (list != null && !list.isEmpty()) {
            return list.get(0);
        }
        return null;
    }

    /**
     * 根据比赛类型和赛季主键获取报名信息列表
     *
     * @param type 比赛类型
     * @param sjId 赛季主键
     * @return 报名信息列表
     */
    @Override
    @SystemServiceLog(description = "根据比赛类型和赛季主键获取报名信息列表")
    public List<FootCupbm> findByTypeAndSj(Boolean type, Long sjId) {
        Map<String, Object> map = new HashMap<>();
        map.put("sj", footSjService.getSj());
        map.put("type", type);
        map.put(DZNUM, 0); //不等于
        return footCupbmMapper.findByMap(map);
    }

    /**
     * 对战
     *
     * @param type 类型
     * @param map  参数
     */
    @Override
    @SystemServiceLog(description = "对战")
    public void bettle(boolean type, Model map) {
        Long sjid = footSjService.getSj();
        map.addAttribute("sj", footSjService.get(sjid));
        map.addAttribute("list16", this.findList(sjid, type, 16));
        map.addAttribute("list8", this.findList(sjid, type, 8));
        map.addAttribute("list4", this.findList(sjid, type, 4));
        map.addAttribute("list2", this.findList(sjid, type, 2));
        map.addAttribute("list1", this.findList(sjid, type, 1));

        map.addAttribute("bflist16", footCupbfService.findBf("time1", sjid, type));
        map.addAttribute("bflist8", footCupbfService.findBf("time2", sjid, type));
        map.addAttribute("bflist4", footCupbfService.findBf("time3", sjid, type));
        map.addAttribute("bflist2", footCupbfService.findBf("time4", sjid, type));
        map.addAttribute("title", type ? "冠军杯" : "联盟杯");
    }
}
